﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FireZone.NativeWMDMInteface;
using System.IO;
using FireZone.DataStructure;
using Microsoft.WindowsAPICodePack.Shell;
using Microsoft.WindowsAPICodePack.Shell.PropertySystem;
using MSWMDMLib;
using System.Runtime.InteropServices;

namespace FireZone
{
    internal static class WMDMMetadataExtensions
    {
        public static object GetMetadataByName(this IWMDMMetaData wmdmdMetaData, string metadataName)
        {
            if (wmdmdMetaData == null) throw new ArgumentNullException("wmdmdMetaData");
            
            WMDM_TAG_DATATYPE   dataType;
            byte[] bValue;
            int     valueLength;
            wmdmdMetaData.QueryByName(metadataName, out dataType, out bValue, out valueLength);
            if(dataType == WMDM_TAG_DATATYPE.WMDM_TYPE_DWORD)
            {
                return BitConverter.ToUInt32(bValue, 0);
            }
            else if(dataType == WMDM_TAG_DATATYPE.WMDM_TYPE_STRING)
            {
                return Encoding.Unicode.GetString(bValue);
            }
            else if(dataType == WMDM_TAG_DATATYPE.WMDM_TYPE_GUID)
            {
                return new Guid(bValue);
            }
            throw new NotImplementedException();
        }
        public static void FillFileMetadataFromParsingName(this IWMDMMetaData wmdmdMetaData, string filename)
        {
            if (wmdmdMetaData == null) throw new ArgumentNullException("wmdmdMetaData");
            if (PhotoItem.FileExtensions.ContainsKey(Path.GetExtension(filename)))
            {
                wmdmdMetaData.FillFileMetadataItem(filename, PhotoItem.VisibleColumns, PhotoItem.FileExtensions);
            }
            else if (VideoItem.FileExtensions.ContainsKey(Path.GetExtension(filename)))
            {
                wmdmdMetaData.FillFileMetadataItem(filename, VideoItem.VisibleColumns, VideoItem.FileExtensions);
            }
            else if (MusicItem.FileExtensions.ContainsKey(Path.GetExtension(filename)))
            {
                wmdmdMetaData.FillFileMetadataItem(filename, MusicItem.VisibleColumns, MusicItem.FileExtensions);
            }
            else if(FlashItem.FileExtensions.ContainsKey(Path.GetExtension(filename)))
            {
                wmdmdMetaData.FillFileMetadataItem(filename, FlashItem.VisibleColumns, FlashItem.FileExtensions);
            }
        }
        private static void FillFileMetadataItem(this IWMDMMetaData metadata, string filename, IDictionary<PropertyKey, string> visibleColumns, IDictionary<string, WMDM_FORMATCODE> fileExtensions)
        {
            metadata.AddItem(WMDM_TAG_DATATYPE.WMDM_TYPE_DWORD, WMDM_DATATYPE_DESC.g_wszWMDMFormatCode, BitConverter.GetBytes((uint)fileExtensions[Path.GetExtension(filename)]), 4);
            using (ShellObject shellobj = ShellObject.FromParsingName(filename))
            {
                foreach (var item in visibleColumns)
                {
                    var shellprop = shellobj.Properties.GetProperty(item.Key);
                    byte[] byteValue = null;
                    object objValue = shellprop.ValueAsObject;
                    if (objValue != null)
                    {
                        if (objValue is int || objValue is uint)
                        {
                            byteValue = BitConverter.GetBytes((uint)shellprop.ValueAsObject);
                            metadata.AddItem(WMDM_TAG_DATATYPE.WMDM_TYPE_DWORD, item.Value, byteValue, byteValue.Length);
                        }
                        else if (objValue is string)
                        {
                            byteValue = UnicodeEncoding.Unicode.GetBytes((string)shellprop.ValueAsObject);
                            metadata.AddItem(WMDM_TAG_DATATYPE.WMDM_TYPE_STRING, item.Value, byteValue, byteValue.Length);
                        }
                        else if (objValue is long || objValue is ulong)
                        {
                            byteValue = BitConverter.GetBytes((ulong)objValue);
                            metadata.AddItem(WMDM_TAG_DATATYPE.WMDM_TYPE_QWORD, item.Value, byteValue, byteValue.Length);
                        }
                        else if (objValue is short || objValue is ushort)
                        {
                            byteValue = BitConverter.GetBytes((ushort)objValue);
                            metadata.AddItem(WMDM_TAG_DATATYPE.WMDM_TYPE_WORD, item.Value, byteValue, byteValue.Length);
                        }
                        else if (objValue is DateTime)
                        {
                            _WMDMDATETIME wmdmDateTime;
                            DateTime netDateTime = ((DateTime)objValue).ToUniversalTime();
                            wmdmDateTime.wDay = (ushort)netDateTime.Day;
                            wmdmDateTime.wHour = (ushort)netDateTime.Hour;
                            wmdmDateTime.wMinute = (ushort)netDateTime.Minute;
                            wmdmDateTime.wMonth = (ushort)netDateTime.Month;
                            wmdmDateTime.wSecond = (ushort)netDateTime.Second;
                            wmdmDateTime.wYear = (ushort)netDateTime.Year;
                            byteValue = wmdmDateTime.MarshalAs();
                            metadata.AddItem(WMDM_TAG_DATATYPE.WMDM_TYPE_DATE, item.Value, byteValue, byteValue.Length);
                        }
                        else
                        {
                            throw new NotImplementedException();
                        }
                    }
                }
            }
        }

    }
}
